package de.mmis.utilities.consoleWrapper;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;

import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

/**
 * A frame where the user can define/change the level of a specific logger
 * 
 * @author martin
 * 
 */
class LogLevelFrame extends JFrame {

	private static LogLevelFrame thisFrame = null;

	public static LogLevelFrame getInstance() {
		if (thisFrame != null)
			return null;

		return thisFrame = new LogLevelFrame();
	}

	final JComboBox category = new JComboBox();

	// singleton
	private LogLevelFrame() {
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		initGUI();
	}

	private void initGUI() {
		setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));

		final JComboBox level = new JComboBox(new Level[] { null, Level.ALL,
				Level.TRACE, Level.DEBUG, Level.INFO, Level.WARN, Level.ERROR,
				Level.FATAL, Level.OFF });

		rebuildCategories();

		category.setEditable(true);
		category.setSelectedItem("root");
		level.setSelectedItem(LogManager.getRootLogger().getLevel());

		category.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				Object o = category.getSelectedItem();
				if (!(o instanceof String))
					return;

				String cat = (String) o;
				Logger l;
				if ("root".equals(cat))
					l = LogManager.getRootLogger();
				else
					l = LogManager.getLogger(cat);

				Level lvl = l.getLevel();
				level.setSelectedItem(lvl);
			}
		});

		JButton cancel = new JButton("Close");
		cancel.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				dispose();
			}
		});

		JButton ok = new JButton("OK");
		ok.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				Object o = category.getSelectedItem();
				if (!(o instanceof String))
					return;

				String cat = (String) o;
				Logger l;
				if ("root".equals(cat))
					l = LogManager.getRootLogger();
				else
					l = LogManager.getLogger(cat);

				Level lvl = (Level) level.getSelectedItem();
				l.setLevel(lvl);

				rebuildCategories();
				category.setSelectedItem(o);
				// deliberately not closing the window
			}
		});

		add(category);
		add(level);
		add(ok);
		add(cancel);

		setResizable(false);
		pack();
	}

	private void rebuildCategories() {
		List<Logger> loggers = new LinkedList<Logger>();
		loggers.add(LogManager.getRootLogger());
		for (Enumeration<?> elogs = LogManager.getCurrentLoggers(); elogs
				.hasMoreElements();) {
			loggers.add((Logger) elogs.nextElement());
		}

		String[] cats = new String[loggers.size()];
		{
			int i = 0;
			for (Logger l : loggers)
				cats[i++] = l.getName();
		}

		Arrays.sort(cats);
		category.setModel(new DefaultComboBoxModel(cats));
	}

	@Override
	public void dispose() {
		super.dispose();
		thisFrame = null;
	}

}
